#include <stdint.h>
// Defination about interrupts description table

// External interrupts
#define VEC_DIVIDE_ERROR            0
#define VEC_DEBUG_EXCEPTION         1
#define VEC_NMI_INT                 2
#define VEC_BREAKPOINT              3
#define VEC_OVERFLOW                4
#define VEC_BOUND_RANGE_EXCEED      5
#define VEC_INVALID_OPCODE          6
#define VEC_DEVICE_NOT_AVAILABLE    7
#define VEC_DOUBLE_FAULT            8
#define VEC_COPROC_SEG_OVERRUN      9
#define VEC_INVALID_TSS             10
#define VEC_SEG_NOT_PRESENT         11
#define VEC_STACK_SEG_FAULT         12
#define VEC_GENERAL_PROTECTION      13
#define VEC_PAGE_FAULT              14
#define VEC_15_RESERVED             15
#define VEC_MATH_FAULT              16
#define VEC_ALIGNMENT_CHECK         17
#define VEC_MACHINE_CHECK           18
#define VEC_SIMD_FLOAT_POINT_EXP    19
#define VEC_VIRTUAL_EXP             20
#define VEC_CRTL_PROTECT_EXP        21

#define IDT_ATTR(dpl)               (((0x70) << 5) | (1 << 15) | (dpl << 13))

#ifdef __x86_64__
typedef unsigned long long int uword_t;
#else
typedef unsigned int uword_t;
#endif

struct interrupt_frame {
    uint32_t eip;
    uint16_t cs;
    uint32_t eflags;
};

/*
    Use this attribute to indicate that the specified function 
    is an interrupt handler or an exception handler.
    Since GCC doesn’t preserve SSE, MMX nor x87 states, 
    the GCC option -mgeneral-regs-only should be used to compile interrupt and exception handlers. 
*/
__attribute__ ((interrupt))
void 
isr0(struct interrupt_frame* frame);